package com.evil.common.oss.service;

import com.aliyun.oss.ClientException;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.internal.OSSHeaders;
import com.aliyun.oss.model.GeneratePresignedUrlRequest;
import com.aliyun.oss.model.GetObjectRequest;
import com.aliyun.oss.model.ObjectMetadata;
import com.evil.common.core.enums.RCodeEnum;
import com.evil.common.core.exception.BusinessException;
import com.evil.common.file.enums.FileServiceProviderEnum;
import com.evil.common.oss.props.AliyunOssProperty;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URL;
import java.net.URLEncoder;
import java.util.Date;

/**
 * @author liyang
 */
@Slf4j
public class AliyunOssFileStorageService extends FileStorageService {

    private OSS client;
    private OSS extranetEndPointClient;
    private final AliyunOssProperty property;

    public AliyunOssFileStorageService(AliyunOssProperty property) {
        this.property = property;
        init();
    }

    private void init() {
        client = new OSSClientBuilder().build(property.getEndPoint(), property.getAccessKey(), property.getSecretKey());
        extranetEndPointClient = new OSSClientBuilder().build(property.getExtranetEndPoint(), property.getAccessKey(), property.getSecretKey());
    }

    /**
     * 获取访问域名
     *
     * @return String
     */
    @Override
    public String getHost() {
        return property.getHost();
    }

    /**
     * 获取预览域名
     *
     * @return String
     */
    @Override
    public String getPreview() {
        return property.getPreview();
    }

    /**
     * 获取访问文件路径
     *
     * @return String
     */
    @Override
    public String getVisitPath() {
        return property.getVisitPath();
    }

    /**
     * 获取OSS类型
     *
     * @return int
     */
    @Override
    public int getServiceProvider() {
        return FileServiceProviderEnum.ALIYUN.getId();
    }

    /**
     * 获取文件URL参数
     *
     * @param path     path
     * @return String fileName=FILE
     */
    @Override
    public String getFileUrl(String path) {
        return this.getPreview() + "/" + path;
    }

    /**
     * 获取文件URL
     *
     * @param path path
     * @param fileName fileName
     */
    @Override
    public String getDownloadUrl(String path, String fileName) {
        return this.getPreview() + "/" + path;
    }

    @Override
    public String upload(byte[] data, String path, String sourceFileName, String contentType, boolean isPreview) {
        return upload(new ByteArrayInputStream(data), path, sourceFileName, contentType, isPreview);
    }

    @Override
    public String upload(InputStream inputStream, String path, String sourceFileName, String contentType, boolean isPreview) {
        if (inputStream == null) {
            return null;
        }
        try {
            // 创建上传Object的Metadata
            ObjectMetadata metadata = new ObjectMetadata();
            if (!isPreview) {
                // 设置下载文件名为源文件名
                metadata.setContentDisposition("attachment;filename=\"" + URLEncoder.encode(sourceFileName, "utf-8") + "\"");
            }
            metadata.setContentEncoding("utf-8");
            metadata.setContentType(contentType);
            client.putObject(property.getBucket(), path, inputStream, metadata);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            throw new BusinessException(RCodeEnum.ERROR_FILE, "文件上传失败，异常：" + e.getMessage());
        }
        return path;
    }

    @Override
    public File getFileByFilePath(String filePath, File file) {
        if (StringUtils.isBlank(filePath) || file == null) {
            return null;
        }
        try {
            client.getObject(new GetObjectRequest(property.getBucket(), filePath), file);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            throw new BusinessException(RCodeEnum.ERROR_FILE, "文件获取失败，异常：" + e.getMessage());
        }
        return file;
    }

    /**
     * 获取下载URL
     *
     * @param filePath       文件path
     * @param fileName       文件名称
     * @param expirationTime 过期时间
     * @return URL
     */
    @Override
    public URL getDownloadUrl(String filePath, String fileName, Date expirationTime) {
        try {
            GeneratePresignedUrlRequest request = new GeneratePresignedUrlRequest(property.getBucket(), filePath);

            // 设置下载文件名为源文件名
            request.addUserMetadata(OSSHeaders.CONTENT_DISPOSITION, "attachment;filename=\"" + URLEncoder.encode(fileName, "utf-8") + "\"");
            return extranetEndPointClient.generatePresignedUrl(request);
        } catch (ClientException | UnsupportedEncodingException e) {
            log.error(e.getMessage(), e);
            throw new BusinessException(RCodeEnum.ERROR_FILE, "获取文件失败，异常：" + e.getMessage());
        }
    }
}
